package com.zerowidth.moc.web.controller.serviceimpl;

import com.zerowidth.db.bean.*;
import com.zerowidth.db.bean.vm.VipInfoVM;
import com.zerowidth.db.op.*;
import com.zerowidth.db.utils.TimeUtils;
import com.zerowidth.moc.web.auth.TokenHelper;
import com.zerowidth.moc.web.bean.YsePayBean;
import com.zerowidth.moc.web.common.ConstVip;
import com.zerowidth.moc.web.controller.service.PayService;
import com.zerowidth.moc.web.pay.ali.AlipayOrderFactory;
import com.zerowidth.moc.web.pay.ali.AlipayOrderResult;
import com.zerowidth.moc.web.pay.hl.HLPayOrderFactory;
import com.zerowidth.moc.web.pay.ls.LSPayOrderFactory;
import com.zerowidth.moc.web.pay.lt.LTOrderBean;
import com.zerowidth.moc.web.pay.lt.LTPayOrderFactory;
import com.zerowidth.moc.web.pay.wx.WXOrderFactory;
import com.zerowidth.moc.web.pay.wx.WXUtil;
import com.zerowidth.moc.web.pay.wx.XmlUtils;
import com.zerowidth.moc.web.resp.ResCode;
import com.zerowidth.moc.web.resp.ResultBean;
import com.zerowidth.moc.web.resp.helper.ResponseCreator;
import com.zerowidth.moc.web.utils.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class PayServiceImpl implements PayService {

    @Override
    public ResponseEntity<ResultBean<VipInfoVM>> getVipEnumList(String appName, String channel, boolean onlyUnbind, boolean dingSafe) {

        VipInfoVM vipInfoVM = new VipInfoVM();

        List<AppConfigBean> beanList = AppConfigDB.getAppConfigData("");
        for (int i = 0; i < com.zerowidth.db.utils.CollectionUtils.size(beanList); i++) {
            if ("pay_type".equals(beanList.get(i).config_key)) {
                AppConfigBean configBean = beanList.get(i);

                if (configBean != null) {
                    vipInfoVM.pay_type = configBean.config_value;
                }
            }
            if ("pay_type2".equals(beanList.get(i).config_key)) {
                AppConfigBean configBean = beanList.get(i);

                if (configBean != null) {
                    vipInfoVM.pay_type2 = configBean.config_value;
                }
            }
        }

        if (dingSafe) {
            vipInfoVM.vip_list = VipEnumDB.getVipEnumList_DingSafe();
        } else {
            if (StringUtils.equals(appName, "顺丰定位")) {
                vipInfoVM.vip_list = VipEnumDB.getVipEnumList_ShunFeng(onlyUnbind);
            } else if (StringUtils.equals(appName, "鹰眼定位")) {
                vipInfoVM.vip_list = VipEnumDB.getVipEnumList_Eye(onlyUnbind);
            } else {
                vipInfoVM.vip_list = VipEnumDB.getVipEnumList(onlyUnbind);
            }
        }

        vipInfoVM.moc_desc_list = VipEnumDB.getMockVipDescList(channel, onlyUnbind);

        if (CollectionUtils.isEmpty(vipInfoVM.vip_list)) {
            return ResponseCreator.creatOk(null, ResCode.ER_40010, "获取会员类型失败");
        } else {
            return ResponseCreator.creatOk(vipInfoVM, ResCode.CODE_OK, "获取会员类型成功");
        }
    }

    @Override
    public ResponseEntity<String> hlPayNotifyFromAliServer(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        boolean flag = HLPayOrderFactory.rsaCheck(params);

        // 商户订单号
        String out_trade_no = params.get("mch_order_no");
        String state = params.get("state");//订单状态，0=支付失败，1=初始化，2=支付中，3=支付成功，4=已撤销，5=订单关闭
        OrderBean orderBean = VipOrderDB.findByOutOrderNo(out_trade_no);

        if (orderBean == null) {
            LogDB.insert("汇联支付发来的通知，此订单不存在");
            return new ResponseEntity<>("fail, mch_order_no not exist", HttpStatus.INTERNAL_SERVER_ERROR);
        }
        if (orderBean.pay_success) {
            LogDB.insert("汇联支付发来的通知，此订单已经处理，state = " + state + ", out_trade_no = " + out_trade_no);
            return new ResponseEntity<>("fail, order has been paid", HttpStatus.INTERNAL_SERVER_ERROR);
        }

        if (flag) {
            LogDB.insert("汇联支付服务器发送过来的异步通知结果验签成功, " + state + " , " + params);

            if (StringUtils.equals(state, "3")) {

                if (!orderBean.pay_success) {
                    // 修改订单支付状态
                    LogDB.insert("汇联支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应收益， out_trade_no = " + out_trade_no);

                    VipOrderDB.alipaySuccess(out_trade_no);

                    if (orderBean.vip_type == 100) {
                        // 充值游戏币
                        int coinNum = (int) (orderBean.amount + 0.5f);
                        String stat_id = orderBean.stat_id;

                        LogDB.insert("汇联支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应数量的游戏币， out_trade_no = " + out_trade_no);
                        boolean result = MockStatUserDB.addGameCoin(stat_id, coinNum);
                        if (result) {
                            LogDB.insert("汇联支付服务器发送过来的异步通知结果，更新游戏币数量成功，coinNum = " + coinNum + " out_trade_no = " + out_trade_no);
                        } else {
                            LogDB.insert("汇联支付服务器发送过来的异步通知结果，更新游戏币数量失败，coinNum = " + coinNum + " out_trade_no = " + out_trade_no);
                        }
                    } else {

                        long cutTime = System.currentTimeMillis();
                        String startTime = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                        VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(orderBean.vip_type);
                        String endTime = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                                TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                        // 支付成功----开始处理业务
                        doPaySuccess(orderBean, vipEnumBean, orderBean.user_id, orderBean.vip_type, startTime, endTime);
                    }

                } else {
                    LogDB.insert("汇联支付服务器发送过来的异步通知结果，准备处理，但此订单已经处理过支付宝成功的通知，并已获得过相应收益， out_trade_no = " + out_trade_no);
                }
            }
            return new ResponseEntity<>("success", HttpStatus.OK);
        } else {
            LogDB.insert("汇联支付服务器发送过来的异步通知结果验签失败, " + params);
            return new ResponseEntity<>("fail", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public ResponseEntity<ResultBean<String>> createAlipayOrder(
            HttpServletRequest request,
            int vipType, String unbind_user_id) {

        String user_id = TokenHelper.getUserIdByToken();
        String stat_id = request.getHeader("stat_id");

        if (StringUtils.isEmpty(user_id)) {
            UserBean userBean = UserDB.findUserByUserId(unbind_user_id);
            if (userBean != null) {
                user_id = userBean.user_id;
            }
        }

        if (StringUtils.isEmpty(user_id)) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的信息");
        }

        //检查此userId号是否被冻结
        FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(user_id);
        if (freezeUserBean != null) {
            String errMsg = freezeUserBean.reason;
            if (StringUtils.isEmpty(errMsg)) {
                errMsg = "此账户已被冻结";
            }
            if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                errMsg += "，解冻时间" + freezeUserBean.free_time;
            }
            return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
        }

        //检查此 设备id号 是否被冻结
        if (StringUtils.isNotEmpty(stat_id)) {
            FreezeUserBean freezeStatBean = FreezeUserDB.findFreezeByStatId(stat_id);
            if (freezeStatBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此设备已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10018, errMsg);
            }
        }

        VipEnumBean bean = VipEnumDB.findVipEnum(vipType);

        if (bean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的会员信息");
        } else if (!bean.vip_enable) {
            return ResponseCreator.creatOk(null, ResCode.ER_40003, "创建订单失败，此类会员已下架");
        }

        String body = bean.vip_name;
        String subject = bean.vip_name + "订单";
        String outTradeNo = UUID.randomUUID().toString();
        String timeOutExpress = "30m";
        String amount = String.format("%.2f", bean.price);
        if (bean.discount_enable) {
            amount = String.format("%.2f", bean.discount_price);
        }
        String productCode = bean.product_code;
        String notifyUrl = DataConfigDB.getValue("aliPayNotifyUrl");

        AlipayOrderResult orderResult = AlipayOrderFactory.createOrderInfo(body, subject, outTradeNo,
                timeOutExpress, amount, productCode, notifyUrl);

        if (orderResult.success) {

            OrderBean orderBean = new OrderBean();
            orderBean.vip_type = vipType;
            orderBean.order_info = orderResult.orderInfo;
            orderBean.user_id = user_id;
            orderBean.out_trade_no = outTradeNo;
            orderBean.amount = Float.parseFloat(amount);
            orderBean.price = bean.price;
            orderBean.subject_value = subject;
            orderBean.pay_success = false;
            orderBean.order_type = OrderBean.TYPE_ALIPAY;
            orderBean.phone_number = "";
            VipOrderDB.insert(orderBean);

            return ResponseCreator.creatOk(orderResult.orderInfo, ResCode.CODE_OK, "创建订单成功");
        } else {
            LogDB.insert(orderResult.exception.getMessage());
            return ResponseCreator.creatOk(null, ResCode.ER_40000, "创建订单失败，" + orderResult.exception.toString());
        }

    }

    @Override
    public ResponseEntity<ResultBean<Void>> alipayNotifyFromAliServer(HttpServletRequest request) {

        LogDB.insert("alipayNotifyFromAliServer");

        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        LogDB.insert("开始验签, params = " + params);
        boolean flag = AlipayOrderFactory.rsaCheckV1(params);

        if (flag) {
            // 商户订单号
            String out_trade_no = params.get("out_trade_no");
            String trade_no = params.get("trade_no");
            String trade_status = params.get("trade_status");
            String total_amount = params.get("total_amount");

            LogDB.insert("支付宝服务器发送过来的异步通知结果验签成功, " + trade_status + " , " + params);

            if (StringUtils.equals(trade_status, "TRADE_SUCCESS")) {
                OrderBean orderBean = VipOrderDB.findByOutOrderNo(out_trade_no);

                if (!orderBean.pay_success) {
                    // 修改订单支付状态
                    LogDB.insert("支付宝服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应收益， out_trade_no = " + out_trade_no);

                    VipOrderDB.alipaySuccess(out_trade_no);

                    long cutTime = System.currentTimeMillis();
                    String startTime = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                    VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(orderBean.vip_type);
                    String endTime = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                            TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                    // 支付成功----开始处理业务
                    doPaySuccess(orderBean, vipEnumBean, orderBean.user_id, orderBean.vip_type, startTime, endTime);

                } else {
                    LogDB.insert("支付宝服务器发送过来的异步通知结果，准备处理，但此订单已经处理过支付宝成功的通知，并已获得过相应收益， out_trade_no = " + out_trade_no);
                }
            }
            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "支付宝异步通知结果处理成功");
        } else {
            LogDB.insert("支付宝服务器发送过来的异步通知结果验签失败, " + params);
            return ResponseCreator.creatOk(null, ResCode.ER_40001, "支付宝异步通知结果验签失败");
        }
    }

    @Override
    public ResponseEntity<ResultBean<String>> createWXOrder(
            HttpServletRequest request, int vipType, String unbind_user_id) {

        String user_id = TokenHelper.getUserIdByToken();
        String stat_id = request.getHeader("stat_id");

        if (StringUtils.isEmpty(user_id)) {
            UserBean userBean = UserDB.findUserByUserId(unbind_user_id);
            if (userBean != null) {
                user_id = userBean.user_id;
            }
        }

        if (StringUtils.isEmpty(user_id)) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的信息");
        }

        //检查此userId号是否被冻结
        FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(user_id);
        if (freezeUserBean != null) {
            String errMsg = freezeUserBean.reason;
            if (StringUtils.isEmpty(errMsg)) {
                errMsg = "此账户已被冻结";
            }
            if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                errMsg += "，解冻时间" + freezeUserBean.free_time;
            }
            return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
        }

        //检查此 设备id号 是否被冻结
        if (StringUtils.isNotEmpty(stat_id)) {
            FreezeUserBean freezeStatBean = FreezeUserDB.findFreezeByStatId(stat_id);
            if (freezeStatBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此设备已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10018, errMsg);
            }
        }

        VipEnumBean bean = VipEnumDB.findVipEnum(vipType);

        if (bean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的会员信息");
        } else if (!bean.vip_enable) {
            return ResponseCreator.creatOk(null, ResCode.ER_40003, "创建订单失败，此类会员已下架");
        }

        String body = bean.vip_name;
        String subject = bean.vip_name + "订单";
        String outTradeNo = UUID.randomUUID().toString().replaceAll("-", "");
        String amountStr = String.format("%.2f", bean.price);
        if (bean.discount_enable) {
            amountStr = String.format("%.2f", bean.discount_price);
        }
        float amount = NumParseUtils.parseFloat(amountStr);

        //todo 测试金额
        //amount = 0.5f;

        String productCode = bean.product_code;
        String notifyUrl = DataConfigDB.getValue("ltPayNotifyUrl");


        LTOrderBean ltOrderBean = LTPayOrderFactory.createOrderInfo(0, subject,
                outTradeNo, notifyUrl, amount);

        if (ltOrderBean != null) {

            OrderBean orderBean = new OrderBean();
            orderBean.vip_type = vipType;
            orderBean.order_info = GsonUtils.toJsonString(ltOrderBean);
            orderBean.user_id = user_id;
            orderBean.out_trade_no = outTradeNo;
            orderBean.amount = Float.parseFloat(amountStr);
            orderBean.price = bean.price;
            orderBean.subject_value = subject;
            orderBean.pay_success = false;
            orderBean.order_type = OrderBean.TYPE_WXPAY;
            VipOrderDB.insert(orderBean);

            return ResponseCreator.creatOk(orderBean.order_info, ResCode.CODE_OK, "创建订单成功");
        }

        return ResponseCreator.creatOk(null, ResCode.CODE_ERR_UNKNOWN, "创建订单失败");
    }

    @Override
    public ResponseEntity<ResultBean<String>> createWXQrOrder(
            HttpServletRequest request, int vipType, String unbind_user_id) {

        String user_id = TokenHelper.getUserIdByToken();
        String stat_id = request.getHeader("stat_id");

        if (StringUtils.isEmpty(user_id)) {
            UserBean userBean = UserDB.findUserByUserId(unbind_user_id);
            if (userBean != null) {
                user_id = userBean.user_id;
            }
        }

        if (StringUtils.isEmpty(user_id)) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的信息");
        }

        //检查此userId号是否被冻结
        FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(user_id);
        if (freezeUserBean != null) {
            String errMsg = freezeUserBean.reason;
            if (StringUtils.isEmpty(errMsg)) {
                errMsg = "此账户已被冻结";
            }
            if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                errMsg += "，解冻时间" + freezeUserBean.free_time;
            }
            return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
        }

        //检查此 设备id号 是否被冻结
        if (StringUtils.isNotEmpty(stat_id)) {
            FreezeUserBean freezeStatBean = FreezeUserDB.findFreezeByStatId(stat_id);
            if (freezeStatBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此设备已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10018, errMsg);
            }
        }

        VipEnumBean bean = VipEnumDB.findVipEnum(vipType);

        if (bean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的会员信息");
        } else if (!bean.vip_enable) {
            return ResponseCreator.creatOk(null, ResCode.ER_40003, "创建订单失败，此类会员已下架");
        }

        String body = bean.vip_name;
        String subject = bean.vip_name + "订单";
        String outTradeNo = UUID.randomUUID().toString().replaceAll("-", "");
        String amountStr = String.format("%.2f", bean.price);
        if (bean.discount_enable) {
            amountStr = String.format("%.2f", bean.discount_price);
        }
        int amount = Math.round(NumParseUtils.parseFloat(amountStr) * 100);

        //todo 测试金额
        //amount = 0.5f;

        String productCode = bean.product_code;
        String notifyUrl = DataConfigDB.getValue("wxPayNotifyUrl");


        Map<String, String> map = WXOrderFactory.createQrCodeOrderInfo(subject, outTradeNo, notifyUrl, amount);

        if (map != null) {

            OrderBean orderBean = new OrderBean();
            orderBean.vip_type = vipType;
            orderBean.order_info = GsonUtils.toJsonString(map);
            orderBean.user_id = user_id;
            orderBean.out_trade_no = outTradeNo;
            orderBean.amount = Float.parseFloat(amountStr);
            orderBean.price = bean.price;
            orderBean.subject_value = subject;
            orderBean.pay_success = false;
            orderBean.order_type = OrderBean.TYPE_WXPAY_QRCODE;
            VipOrderDB.insert(orderBean);

            return ResponseCreator.creatOk(orderBean.order_info, ResCode.CODE_OK, "创建扫码订单成功");
        }

        return ResponseCreator.creatOk(null, ResCode.CODE_ERR_UNKNOWN, "创建扫码订单失败");
    }

    @Override
    public ResponseEntity<ResultBean<Void>> wxPayNotifyFromWxServer(HttpServletRequest request) {
        // 读取参数，解析Xml为map
        Map<String, String> map = null;
        try {
            map = XmlUtils.transferXmlToMap(HttpUtils.readRequest(request));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 转换为有序 map，判断签名是否正确
        boolean isSignSuccess = false;
        try {
            isSignSuccess = WXUtil.checkSign(new TreeMap<String, String>(map));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String out_trade_no = map.get("out_trade_no");
        String return_code = map.get("return_code");

        if (isSignSuccess) {
            LogDB.insert("微信支付服务器发送过来的异步通知结果验签成功, out_trade_no = " + out_trade_no);

            // 签名校验成功，说明是微信服务器发出的数据
            if ("SUCCESS".equals(return_code)) {
                LogDB.insert("微信支付服务器发送过来的异步通知结果验签成功-支付成功，out_trade_no = " + out_trade_no);

                //尝试查找 购买会员订单
                OrderBean orderBean = VipOrderDB.findByOutOrderNo(out_trade_no);
                if (orderBean != null && !orderBean.pay_success) {
                    // 修改订单支付状态
                    VipOrderDB.alipaySuccess(out_trade_no);

                    // 支付成功----开始处理业务
                    if (orderBean.vip_type == 100) {
                        // 充值游戏币
                        int coinNum = (int) (orderBean.amount + 0.5f);
                        String stat_id = orderBean.stat_id;

                        LogDB.insert("微信支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应数量的游戏币， out_trade_no = " + out_trade_no);
                        boolean result = MockStatUserDB.addGameCoin(stat_id, coinNum);
                        if (result) {
                            LogDB.insert("微信支付服务器发送过来的异步通知结果，更新游戏币数量成功，coinNum = " + coinNum + " out_trade_no = " + out_trade_no);
                        } else {
                            LogDB.insert("微信支付服务器发送过来的异步通知结果，更新游戏币数量失败，coinNum = " + coinNum + " out_trade_no = " + out_trade_no);
                        }

                    } else {
                        //购买宝宝定位会员 成功通知

                        long cutTime = System.currentTimeMillis();
                        String startTime = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                        VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(orderBean.vip_type);
                        String endTime = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                                TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                        //检查此userId号是否被冻结
                        FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(orderBean.user_id);
                        if (freezeUserBean != null) {
                            String errMsg = freezeUserBean.reason;
                            if (StringUtils.isEmpty(errMsg)) {
                                errMsg = "此账户已被冻结";
                            }
                            if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                                errMsg += "，解冻时间" + freezeUserBean.free_time;
                            }
                            LogDB.insert("微信支付服务器发送过来的异步通知结果，准备将此订单支付状态改为成功时，发现此用户被冻结， out_trade_no = " + out_trade_no + " , userId = " + orderBean.user_id);
                            return ResponseCreator.creatOk(null, ResCode.ER_40032, errMsg);
                        }


                        // 支付成功----开始处理业务
                        LogDB.insert("微信支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应收益， out_trade_no = " + out_trade_no);
                        doPaySuccess(orderBean, vipEnumBean, orderBean.user_id, orderBean.vip_type, startTime, endTime);
                    }

                } else {
                    LogDB.insert("微信支付服务器发送过来的异步通知结果，准备处理，但此订单已经处理过微信支付成功的通知，并已获得过相应收益， out_trade_no = " + out_trade_no);
                }

            } else {
                //支付失败
                LogDB.insert("微信支付服务器发送过来的异步通知结果验签成功-支付失败，out_trade_no = " + out_trade_no);
            }
            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "微信支付异步通知结果处理成功");
        } else {
            LogDB.insert("微信支付异步通知签名校验失败, return_code = " + return_code);
            // 签名校验失败（可能不是微信服务器发出的数据）
            return ResponseCreator.creatOk(null, ResCode.ER_40031, "微信支付异步通知结果处理失败");
        }
    }

    /**
     * 支付成功 的 业务处理
     */
    private void doPaySuccess(OrderBean orderBean, VipEnumBean vipEnumBean,
                              String userId, int vipType, String vip_start_time, String vip_end_time) {
        if (StringUtils.equals(DataConfigDB.getValue("unbind_vip_type"), vipType + "")) {
            //解绑设备，支付成功
            String unbindPhone = orderBean.user_id;
            UserBean userBean = UserDB.findUserByUserId(unbindPhone);
            if (userBean != null) {
                MockStatUserDB.clearDeviceInfo(userBean.user_id);
            }
        } else if (StringUtils.equals(DataConfigDB.getValue("ding_safe_vip_type"), vipType + "")) {
            //购买钉钉安全包，支付成功

            UserDB.updateDingSafeVersion(orderBean.user_id, 1);
        } else {
            //购买会员，支付成功

            UserBean userBean = UserDB.findUserByUserId(userId);

            if (StringUtils.isEmpty(userBean.vip_end_time)) {
                //用户首次购买时，直接修改起止时间
                UserDB.updateVipType(userId, vipType, vip_start_time, vip_end_time);
            } else if (TimeUtil.timePass(userBean.vip_end_time) >= 0) {
                //用户的会员时间已经到期，再次购买时，直接修改起止时间
                UserDB.updateVipType(userId, vipType, vip_start_time, vip_end_time);
            } else {
                //用户的会员时间没有到期，再次购买时，应该是从用户会员结束时间开始续费时间

                String startTime = userBean.vip_end_time;
                long userEndTimeStamp = TimeParseUtil.parseYYYYMMDDHHmmss(userBean.vip_end_time).getTimeInMillis();
                String endTime = TimeUtils.convert(userEndTimeStamp + vipEnumBean.vip_duration * 1000,
                        TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                UserDB.updateVipType(userId, vipType, startTime, endTime);
            }

            if (vipEnumBean.vip_type == 7) {
                //购买的是 钉钉专属会员，直接赠送 钉钉安全包
                UserDB.updateDingSafeVersion(userId, 1);
            }

        }
    }

    public ResponseEntity<ResultBean<Void>> exchange(HttpServletRequest request, String old_stat_id, String new_stat_id) {
        String userId = TokenHelper.getUserIdByToken();

        if (StringUtils.length(old_stat_id) == 8) {
            //激活码激活

            int activeCodeVipType = ActiveDB.findVipType(old_stat_id);
            if (activeCodeVipType <= 0) {
                if (ActiveDB.findVipType2(old_stat_id) > 0) {
                    return ResponseCreator.creatOk(null, ResCode.ER_70014, "此激活码已被使用，请勿重复激活");
                }
                return ResponseCreator.creatOk(null, ResCode.ER_70014, "激活码不存在");
            }

            long cutTime = System.currentTimeMillis();
            String vip_start_time = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
            VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(activeCodeVipType);
            String vip_end_time = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                    TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

            UserBean userBean = UserDB.findUserByUserId(userId);

            if (StringUtils.isEmpty(userBean.vip_end_time)) {
                //用户首次购买时，直接修改起止时间
                UserDB.updateVipType(userId, activeCodeVipType, vip_start_time, vip_end_time);
            } else if (TimeUtil.timePass(userBean.vip_end_time) >= 0) {
                //用户的会员时间已经到期，再次购买时，直接修改起止时间
                UserDB.updateVipType(userId, activeCodeVipType, vip_start_time, vip_end_time);
            } else {
                //用户的会员时间没有到期，再次购买时，应该是从用户会员结束时间开始续费时间

                String startTime = userBean.vip_end_time;
                long userEndTimeStamp = TimeParseUtil.parseYYYYMMDDHHmmss(userBean.vip_end_time).getTimeInMillis();
                String endTime = TimeUtils.convert(userEndTimeStamp + vipEnumBean.vip_duration * 1000,
                        TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                UserDB.updateVipType(userId, activeCodeVipType, startTime, endTime);
            }

            ActiveDB.update(old_stat_id, userId);

            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "激活成功，" + vipEnumBean.vip_name);

        }

        return ResponseCreator.creatOk(null, ResCode.CODE_ERR_UNKNOWN, "激活失败，激活码长度不对");

    }

    private static ReentrantLock lock = new ReentrantLock();

    public ResponseEntity<String> lsPayNotifyFromWxServer(HttpServletRequest request) {
        try {
            lock.lock();

            Map<String, String> params = new TreeMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                String[] values = requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                params.put(name, valueStr);
            }

            boolean flag = LSPayOrderFactory.rsaCheck(params);

            // 商户订单号
            String out_trade_no = params.get("mch_order_no");
            String state = params.get("state");//支付订单状态 0-订单生成 1-支付中 2-支付成功 3-支付失败 4-已撤销 5-已退款 6-订单关闭
            OrderBean orderBean = VipOrderDB.findByOutOrderNo(out_trade_no);

            if (orderBean == null) {
                LogDB.insert("联速支付发来的通知，此订单不存在");
                return new ResponseEntity<>("商户自身系统内不存在此订单号", HttpStatus.INTERNAL_SERVER_ERROR);
            }
            if (orderBean.pay_success) {
                LogDB.insert("联速支付发来的通知，此订单已经处理，state = " + state + ", out_trade_no = " + out_trade_no);
                return new ResponseEntity<>("商户系统已经处理过此订单", HttpStatus.INTERNAL_SERVER_ERROR);
            }

            if (flag) {
                LogDB.insert("联速支付服务器发送过来的异步通知结果验签成功, " + state + " , " + params);

                if (StringUtils.equals(state, "2")) {

                    if (!orderBean.pay_success) {
                        // 修改订单支付状态
                        LogDB.insert("联速支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应收益， out_trade_no = " + out_trade_no);

                        VipOrderDB.alipaySuccess(out_trade_no);


                        long cutTime = System.currentTimeMillis();
                        String startTime = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                        VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(orderBean.vip_type);
                        String endTime = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                                TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                        // 支付成功----开始处理业务
                        doPaySuccess(orderBean, vipEnumBean, orderBean.user_id, orderBean.vip_type, startTime, endTime);

                    } else {
                        LogDB.insert("联速支付服务器发送过来的异步通知结果，准备处理，但此订单已经处理过支付宝成功的通知，并已获得过相应收益， out_trade_no = " + out_trade_no);
                    }

                    return new ResponseEntity<>(null, HttpStatus.OK);
                }

                return new ResponseEntity<>("用户支付未成功，不予以处理", HttpStatus.INTERNAL_SERVER_ERROR);
            } else {
                LogDB.insert("联速支付服务器发送过来的异步通知结果验签失败, " + params);
                return new ResponseEntity<>("未知原因", HttpStatus.SERVICE_UNAVAILABLE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

        return new ResponseEntity<>("未知原因", HttpStatus.SERVICE_UNAVAILABLE);
    }

    @Override
    public ResponseEntity<String> ltPayNotify(HttpServletRequest request) {

        LogDB.insert("蓝兔支付服务器发送过来的异步通知");

        try {
            lock.lock();

            Map<String, String> allParams = new TreeMap<>();

            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                String[] values = requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                allParams.put(name, valueStr);
            }

            Map<String, String> singParams = new TreeMap<>();
            singParams.put("code", allParams.get("code"));
            singParams.put("timestamp", allParams.get("timestamp"));
            singParams.put("mch_id", allParams.get("mch_id"));
            singParams.put("order_no", allParams.get("order_no"));
            singParams.put("out_trade_no", allParams.get("out_trade_no"));
            singParams.put("pay_no", allParams.get("pay_no"));
            singParams.put("total_fee", allParams.get("total_fee"));
            String signComputeStr = LTPayOrderFactory.createSign(singParams);

            LogDB.insert("allParams = " + allParams);
            LogDB.insert("signComputeStr = " + signComputeStr);

            boolean flag = StringUtils.equals(signComputeStr, allParams.get("sign"));

            // 商户订单号
            String out_trade_no = allParams.get("out_trade_no");
            String code = allParams.get("code");//支付订单状态 0-订单生成 1-支付中 2-支付成功 3-支付失败 4-已撤销 5-已退款 6-订单关闭

            OrderBean orderBean = VipOrderDB.findByOutOrderNo(out_trade_no);

            if (orderBean == null) {
                LogDB.insert("蓝兔支付发来的通知，此订单不存在");
                return new ResponseEntity<>("FAIL", HttpStatus.SERVICE_UNAVAILABLE);
            }
            if (orderBean.pay_success) {
                LogDB.insert("蓝兔支付发来的通知，此订单已经处理，code = " + code + ", out_trade_no = " + out_trade_no);
                return new ResponseEntity<>("SUCCESS", HttpStatus.OK);
            }

            if (flag) {
                LogDB.insert("蓝兔支付服务器发送过来的异步通知结果验签成功, code = " + code + " , " + allParams);

                if (StringUtils.equals(code, "0")) {

                    if (!orderBean.pay_success) {
                        // 修改订单支付状态
                        LogDB.insert("蓝兔支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应收益， out_trade_no = " + out_trade_no);

                        VipOrderDB.alipaySuccess(out_trade_no);


                        long cutTime = System.currentTimeMillis();
                        String startTime = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                        VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(orderBean.vip_type);
                        String endTime = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                                TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                        // 支付成功----开始处理业务
                        doPaySuccess(orderBean, vipEnumBean, orderBean.user_id, orderBean.vip_type, startTime, endTime);

                    } else {
                        LogDB.insert("蓝兔支付服务器发送过来的异步通知结果，准备处理，但此订单已经处理过支付宝成功的通知，并已获得过相应收益， out_trade_no = " + out_trade_no);
                    }

                    return new ResponseEntity<>("SUCCESS", HttpStatus.OK);
                }

                return new ResponseEntity<>("FAIL", HttpStatus.SERVICE_UNAVAILABLE);
            } else {
                LogDB.insert("蓝兔支付服务器发送过来的异步通知结果验签失败, " + allParams);
                return new ResponseEntity<>("FAIL", HttpStatus.SERVICE_UNAVAILABLE);
            }
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }


        return new ResponseEntity<>("FAIL", HttpStatus.SERVICE_UNAVAILABLE);
    }

    @Override
    public ResponseEntity<ResultBean<YsePayBean>> createYSEQrOrder(HttpServletRequest request, int vipType,
                                                                   String unbind_user_id) {

        String user_id = TokenHelper.getUserIdByToken();
        String stat_id = request.getHeader("stat_id");

        if (StringUtils.isEmpty(user_id)) {
            user_id = unbind_user_id;
        }

        UserBean userBean = UserDB.findUserByUserId(user_id);

        if (StringUtils.isEmpty(user_id) || userBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的信息");
        }

        VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(vipType);

        if (vipEnumBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_40002, "创建订单失败，未查询到指定的会员信息");
        } else if (!vipEnumBean.vip_enable) {
            return ResponseCreator.creatOk(null, ResCode.ER_40003, "创建订单失败，此类会员已下架");
        }


        float needPayPrice = 0;
        boolean needToInsertDB = true;

        OrderBean myUnPayOrder = VipOrderDB.findMyUnPayOrder(vipType, user_id);

        if (myUnPayOrder != null) {
            needPayPrice = myUnPayOrder.amount;
            needToInsertDB = false;
        } else {
            List<OrderBean> unPayOrderList = VipOrderDB.findUnPayOrder(vipType);
            if (CollectionUtils.isEmpty(unPayOrderList)) {
                needPayPrice = vipEnumBean.discount_price;
            } else {
                OrderBean minPrice = CollectionUtils.getMin(unPayOrderList, new Comparator<OrderBean>() {
                    @Override
                    public int compare(OrderBean o1, OrderBean o2) {
                        return o1.amount < o2.amount ? -1 : 1;
                    }
                });
                needPayPrice = minPrice.amount - 0.01f;
            }
        }

        YsePayBean ysePayBean = new YsePayBean();

        ysePayBean.qrcode_url = DataConfigDB.getValue("offLineQrCodeUrlWx");
        ysePayBean.money = String.format("%.2f", needPayPrice);
        ysePayBean.comment = "请在10分钟内完成以下所有操作\n" +
                "  1、保存收款码到手机相册，支持截屏保存\n" +
                "  2、用微信扫一扫相册中的收款码，输入正确的付款金额，完成支付\n\n" +
                "注意：\n" +
                "  1、禁止随意修改金额，否则将导致支付无效，金额精确到小数点后两位\n" +
                "  2、不需要担心软件怎么知道是哪个用户付的款，自有方法判断，请放心支付\n" +
                "  3、如果微信提示支付风险，请无视并申请解除即可\n";

        if (needToInsertDB) {
            OrderBean orderBean = new OrderBean();
            orderBean.vip_type = vipType;
            orderBean.order_info = "";
            orderBean.user_id = user_id;
            orderBean.out_trade_no = "";
            orderBean.amount = Float.parseFloat(ysePayBean.money);
            orderBean.price = vipEnumBean.price;
            orderBean.subject_value = vipEnumBean.vip_name + "订单";
            orderBean.pay_success = false;
            orderBean.order_type = OrderBean.TYPE_WXPAY;
            orderBean.phone_number = "";
            VipOrderDB.insert(orderBean);
        }

        return ResponseCreator.creatOk(ysePayBean, ResCode.CODE_OK, "创建订单成功");
    }

    @Override
    public ResponseEntity<ResultBean<String>> androidPayNotifyFromPhone(HttpServletRequest request, String channel, int payType, String money) {

        LogUtil.e("payNotify", String.format("收到一条支付成功的通知，%s, %d, %s", channel, payType, money));

        LogDB.insert(String.format("收到一条支付成功的通知，%s, %d, %s", channel, payType, money));

        OrderBean payOrder = VipOrderDB.findMoneyPayOrder(money);

        if (payOrder == null) {
            LogDB.insert(String.format("未找到支付订单记录，支付丢失，%s, %d, %s", channel, payType, money));

            return ResponseCreator.creatOk("未找到支付订单记录, 金额=" + money, ResCode.CODE_ERR_UNKNOWN, "通知失败");
        } else {

            boolean result = VipOrderDB.qrPaySuccess(payOrder.id);

            if (result) {
                //购买宝宝定位会员 成功通知

                long cutTime = System.currentTimeMillis();
                String startTime = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(payOrder.vip_type);
                String endTime = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                        TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                // 支付成功----开始处理业务
                LogDB.insert("微信支付服务器发送过来的异步通知结果，将此订单支付状态改为成功，并获得相应收益");
                doPaySuccess(payOrder, vipEnumBean, payOrder.user_id, payOrder.vip_type, startTime, endTime);

                return ResponseCreator.creatOk("服务器处理成功, id = " + payOrder.id, ResCode.CODE_OK, "通知成功");
            } else {
                LogDB.insert(String.format("更新订单状态失败，%s, %d, %s", channel, payType, money));

                return ResponseCreator.creatOk("更新订单状态失败, 金额=" + money, ResCode.CODE_ERR_UNKNOWN, "通知失败");
            }

        }
    }

}
